//
//  main.c
//  Bit operation
//
//  Created by admin on 2019/7/19.
//  Copyright © 2019 猫爷爷的酱醋茶. All rights reserved.
//

#include <stdio.h>
/*
 
 位运算：
 指的是1个二进制数据的每一位来参与运算。
 位运算的前提：是这个数必须是1个二进制。
 
 注意：
 1）参与位运算的二进制数据必须是补码形式。
 2）位运算的结果也是二进制的补码形式。
 
 
 
 1.按位与：&   例:BitwiseAnd();
    参与按位与的两个二进制数。如果都为1，那么结果为1；只要有0，结果为0；
 
    3 & 2：
    3的补码：00000000 00000000 00000000 00000011
    2的补码：00000000 00000000 00000000 00000010
 ------------------------------------------------
           00000000 00000000 00000000 00000010    为2.
 
    -3 & 4:
    -3的原码：10000000 00000000 00000000 00000011
    -3的反码：11111111 11111111 11111111 11111100
    -3的补码：11111111 11111111 11111111 11111101
    4的补码： 00000000 00000000 00000000 00000100
 -------------------------------------------------
            00000000 00000000 00000000 00000100  为4.
 
    -3 & -4:
    -4的原码：10000000 00000000 00000000 00000100
    -4的反码：11111111 11111111 11111111 11111011
    -4的补码：11111111 11111111 11111111 11111100
    -3的补码：11111111 11111111 11111111 11111101
 ------------------------------------------------
            11111111 11111111 11111111 11111100
 结果为补码，需将其还原为反码：
            11111111 11111111 11111111 11111011
 即原码为：
            10000000 00000000 00000000 00000100  为-4.
 
 
 
 任何数按位与1的结果：是这个数的最低位。
 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
 00000000 00000000 00000000 00000001
--------------------------------------
 00000000 00000000 00000000 0000000？
 
 偶数的最低数一定是0，奇数的最低位一定是1.
 所以，如果要判断这个数是奇数还是偶数，只要用这个数与1就可以了。
 如果结果为1，那么就是奇数；如果结果为0，那么就是偶数。
 
 
 
 
 
 2. 按位或: |  例:BitwiseOr();
    参与按位或的两个二进制数。只要有1，结果为1；
 
    3|2：
    3的原码：00000000 00000000 00000000 00000011
    2的原码：00000000 00000000 00000000 00000010
 -------------------------------------------------
           00000000 00000000 00000000 00000011     为3. 例：
 
    -3 | -4:
    -3的原码：10000000 00000000 00000000 00000011
    -3的反码：11111111 11111111 11111111 11111100
    -3的补码：11111111 11111111 11111111 11111101
    -4的补码：11111111 11111111 11111111 11111100
 --------------------------------------------------
            11111111 11111111 11111111 11111101
    转回反码：11111111 11111111 11111111 11111100
    转回原码：10000000 00000000 00000000 00000011
                                                为 -3.
 
 
 
 
 3. 按位取反：~  例:BitwiseNegation();
    单目运算.将这个二进制数的每一位取反。 例：~3.
 
    3的补码：00000000 00000000 00000000 00000011
   按位取反：11111111 11111111 11111111 11111100
将其转回反码：11111111 11111111 11111111 11111011
    即原码： 10000000 00000000 00000000 00000100  为 -4.
 
 
 
 
 4.按位异或：^   例:BitwiseXOR();
    参与按位或的两个二进制数吗，相同为0，不同为1.
 
    2^3
    2的补码：00000000 00000000 00000000 00000010
    3的补码：00000000 00000000 00000000 00000011
 ------------------------------------------------
           00000000 00000000 00000000 00000001 为 1
 
 使用异或可以实现两个数的交换。
 a b
 a = a ^ b
 b = a ^ b
 a = a ^ b
 
 例：a = 12  b = 15
 a的补码: 00000000 00000000 00000000 00001100
 b的补码: 00000000 00000000 00000000 00001111
 --------------------------------------------
         00000000 00000000 00000000 00000011 a = a^b = 3
 
 3的补码： 00000000 00000000 00000000 00000011
 b的补码： 00000000 00000000 00000000 00001111
 --------------------------------------------
         00000000 00000000 00000000 00001100  b = a^b = 12
 
 3的补码： 00000000 00000000 00000000 00000011
 12的补码：00000000 00000000 00000000 00001100
 --------------------------------------------
         00000000 00000000 00000000 00001111 a = a^b = 15
 
 即结果a=15;b=12; 例：ExchangeOfNumber();
 
 
 
 
 5. 按位左移 << 例：ShiftLeft();
    参与按位左移运算的二进制数据，向左移动指定的位数，低位不够补0，高位溢出舍弃。
 
   注意：
    1）左移运算可能会改变其正负性；
    2）将1个数左移n位，相当于将这个数乘以2的n次方。
        3 << 2  -> 3 * 2^2
        16 << 3 -> 16 * 2^3
    5 * 16 也可以表示为 5 << 4 而且计算的速度更快，因为直接二进制计算
 
 
 
 
 6.按位右移 >>  例：ShiftRight();
    参与按位右移的二进制数据，向右移动指定的位数，低位溢出丢弃，高位补符号位。
 
    3 >> 2
    3的补码： 00000000 00000000 00000000 00000011
            0000000000 00000000 00000000 000000 11  即为 0
 
    -16 >> 3
    -16的原码：10000000 00000000 00000000 00010000
    -16的反码：11111111 11111111 11111111 11101111
    -16的补码：11111111 11111111 11111111 11110000
 -16 >> 3 ：    11111111 11111111 11111111 11110 000
    即为      11111111 11111111 11111111 11111110
    还原为反码：11111111 11111111 11111111 11111101
    还原为原码：10000000 00000000 00000000 00000010
                                                即为 -2
 
 
  注意：
    1)右移运算不会改变正负性；
    2）1个数按位右移n位，相当于这个数除以2的n次方。
 
 
 
 
 */

//按位与
void BitwiseAnd(void);
//使用按位与判断奇偶性
void JudgingParity(void);

//按位或
void BitwiseOr(void);

//按位取反
void BitwiseNegation(void);

//按位异或
void BitwiseXOR(void);

//交换两个数
void ExchangeOfNumber(void);

//按位左移
void ShiftLeft(void);

//按位右移
void ShiftRight(void);




int main(int argc, const char * argv[]) {
    ShiftRight();
    return 0;
}

//按位右移
void ShiftRight(void)
{
    int num = -16 >> 3;
    printf("-16 >> 3 按位左移为 %d\n",num);
}

//按位左移
void ShiftLeft(void)
{
    int num = 16 << 3;
    printf("16 << 3 按位左移为 %d\n",num);
}

//交换两个数
void ExchangeOfNumber(void)
{
    int num1 = 125;
    int num2 = 356;
    
    num1 = num1 ^ num2;
    num2 = num1 ^ num2;
    num1 = num1 ^ num2;
    
    printf("num1 = %d,num2 = %d\n",num1,num2);
}

//按位异或
void BitwiseXOR(void)
{
    int num = 3 ^ 2;
    printf("3 ^ 2的按位与为 %d\n",num);
}

//按位取反
void BitwiseNegation(void)
{
    int num = ~3;
    printf("3 的按位取反为 %d\n",num);
}

//按位或
void BitwiseOr(void)
{
    int num = 3 | 2;
    printf("3 | 2的按位与为 %d\n",num);
    int num1 = -3 | -4;
    printf("-3 | -4的按位与为 %d\n",num1);
}

//使用按位与判断奇偶性
void JudgingParity(void)
{
    printf("请输入需要判断奇偶性的数：\n");
    int number = 0;
    scanf("%d",&number);
    if((number & 1) == 0)
    {
        printf("这个数为偶数\n");
    }else{
        printf("这个数为奇数\n");
    }
    
}

//按位与
void BitwiseAnd(void)
{
    int num = 3 & 2;
    printf("3 & 2的按位与为 %d\n",num);
    int num1 = -3 & 4;
    printf("-3 & 4的按位与为 %d\n",num1);
    int num2 = -3 & -4;
    printf("-3 & -4的按位与为 %d\n",num2);
}
